﻿package makeeasier.net {
	
	import flash.events.*;
	import flash.net.*;
	import flash.utils.*;
	
	
	public class MultipleUploader extends EventDispatcher {
		
		private var _url:URLRequest;
		private var _uploaderInstance:Number;
		private var _fileReferenceList:FileReferenceList;
		private var _fileList:Vector.<Object>;
		private var _fileTypes:Vector.<String>;
		private var _ff:FileFilter;
		private var _que:Number;
		private var _current:Number;
		private var _concurrentUpload:Number;
		private var _finished:Number;
		private var _failed:Number;
		private var _lastProgressObject:Object;
		private var _lastProgress:Number;
		private var _lastComplete:Number;
		private var _uploadDataFieldName:String;
		private var _testMode:Boolean;
		
		
		public function MultipleUploader(){
			_uploaderInstance = 2;
			_fileReferenceList = new FileReferenceList();
			_fileList = new Vector.<Object>();
			_fileTypes = new Vector.<String>();
			_finished = 0;
			_failed = 0;
			_que = 0;
			_current = 0;
			_concurrentUpload = 0;
			_lastProgress = 0;
			_lastProgressObject = null;
			_lastComplete = 0;
			_url = null;
		}
		
		private function initialize():void{
			var fileTypesStringArray:Vector.<String> = new Vector.<String>();
			for(var i=0; i<_fileTypes.length; i++){
				fileTypesStringArray.push("*."+_fileTypes[i]);
			}
			var fileTypesString:String = fileTypesStringArray.join("; ");
			_ff = new FileFilter("Files ("+fileTypesString.replace("; ",", ")+")", fileTypesString);
		}
		
		public function addFileType(s:String):void{
			_fileTypes.push(s);
		}
		
		public function start():void{
			if(_url == null || !_fileList.length){
				return;
			}
			dispatchEvent(new Event("start"));
			upload();
		}
		
		private function upload():void{
			if( _que < (_uploaderInstance <= _fileList.length ? _uploaderInstance : _fileList.length) ){
				//trace("UPLOADING START: "+_fileList[_current].file.name);
				_fileList[_current].que = _que;
				_fileList[_current].currentId = _current;
				_fileList[_current].file.addEventListener(IOErrorEvent.IO_ERROR, onUploadFail);
				_fileList[_current].file.addEventListener("uploadCompleteData", onUploadComplete);
				_fileList[_current].file.addEventListener("progress", onProgress);
				_fileList[_current].file.upload(_url,_uploadDataFieldName,_testMode);
				dispatchEvent(new Event("uploadStart"));
				_que++;
				_concurrentUpload++;
				_current++;
				upload();
			}
		}
		
		private function onUploadComplete(e:Event):void{
			//trace("UPLOADING FINISH: "+e.target.name);
			for(var i=0; i<_fileList.length; i++){
				if(_fileList[i].file == e.target){
					_lastComplete = i;
					break;
				}
			}
			dispatchEvent(e);
			_finished++;
			_concurrentUpload--;
			if( _finished == _fileList.length ){
				trace("COMPLETED!");
				dispatchEvent(new Event("complete"));
				return;
			}
			if(_que == _uploaderInstance){
				_uploaderInstance = 1;
				_que = 0;
				if(_current < _fileList.length){
					upload();
				}
			}
			//trace("CONCURRENT UPLOAD:"+_concurrentUpload);
		}
		
		private function onUploadFail(e:Event):void{
			_failed++;
		}
		
		private function onProgress(e:ProgressEvent):void{
			for(var i=0; i<_fileList.length; i++){
				if( _fileList[i].file == e.target ){
					_lastProgress = e.bytesLoaded / e.bytesTotal;
					_fileList[i].progress = _lastProgress;
					_lastProgressObject = _fileList[i];
					dispatchEvent(new Event("progress"));
					break;
				}
			}
		}
		
		private function openBrowseComplete(e:Event):void{
			var ii = 0;
			for each( var i in _fileReferenceList.fileList){
				var obj:Object = new Object();
				obj.id = ii;
				obj.file = i;
				obj.progress = 0;
				obj.que = 0;
				obj.currentId = 0;
				_fileList.push(obj);
				ii++;
			}
			dispatchEvent(new Event("open"));
		}
		
		public function open():void{
			initialize();
			_fileReferenceList.browse([_ff]);
			_fileReferenceList.addEventListener("select",openBrowseComplete);
		}
		
		public function get instance():Number{
			return _uploaderInstance;
		}
		
		public function set instance(i:Number):void{
			_uploaderInstance = i;
		}
		
		public function get url():URLRequest{
			return _url;
		}
		
		public function set url(u:URLRequest):void{
			_url = u;
		}
		
		public function get uploadDataFieldName():String{
			return _uploadDataFieldName;
		}
		
		public function set uploadDataFieldName(u:String):void{
			_uploadDataFieldName = u;
		}
		
		public function get testMode():Boolean{
			return _testMode;
		}
		
		public function set testMode(u:Boolean):void{
			_testMode = u;
		}
		
		public function get que():Number{
			return _que;
		}
		
		public function get current():Number{
			return _current;
		}
		
		public function get lastProgress():Number{
			return _lastProgress;
		}
		
		public function get lastComplete():Number{
			return _lastComplete;
		}
		
		public function get lastProgressObject():Object{
			return _lastProgressObject;
		}
		
		public function getFile(n:Number):FileReference{
			return _fileList[n].file;
		}
	}
	
}
